import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.text.DefaultCaret;

public class ChatClient {

	JFrame theFrame;
	JTextArea display;
	Socket chatSocket;
	PrintWriter writer;
	BufferedReader reader;
	String name = null;
	JTextField field;
	JFrame frame;
	JTextField theField;
	JScrollPane scroller;
	Thread flashFocus;
	int id = 0;
	
	
	public static void main(String[] args){
		ChatClient gui = new ChatClient();
		gui.nameMaker();
	}
	
	public void go(){
		
		theFrame = new JFrame(name);
		JPanel thePanel = new JPanel();
		Box theBox = new Box(BoxLayout.X_AXIS);
		thePanel.setLayout(new BoxLayout(thePanel, BoxLayout.Y_AXIS));
		display = new JTextArea(15,35);
		display.setWrapStyleWord(true);
		display.setLineWrap(true);
		display.setEditable(false);
		
		scroller = new JScrollPane(display);
		scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		
		theField = new JTextField(6);
		theField.addActionListener(new TheFieldListener());
		JButton theButton = new JButton("Send");
		theButton.addActionListener(new TheButtonListener());
		theBox.add(theField);
		theBox.add(theButton);
		
		thePanel.add(BorderLayout.CENTER, scroller);
		thePanel.add(BorderLayout.SOUTH, theBox);
		
		
		Thread msgGetter = new Thread(new MsgGetter());
		msgGetter.start();
		//DefaultCaret caret = (DefaultCaret)display.getCaret();
		//caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
		theFrame.addWindowFocusListener(new TheFrameFocusListenr());
		theFrame.setResizable(false);
		theFrame.setDefaultCloseOperation(theFrame.EXIT_ON_CLOSE);
		theFrame.setSize(300,300);
		theFrame.add(BorderLayout.CENTER, thePanel);
		theFrame.pack();
		theFrame.setVisible(true);
		
		theFrame.addWindowListener(new java.awt.event.WindowAdapter() {
		    @Override
		    public void windowClosing(java.awt.event.WindowEvent windowEvent) {
		    	try{
	    			writer.println("Server: " + name + " left");
	    			writer.flush();
	    			}catch(Exception ex){theField.setText("Couldn't send");theField.requestFocus();}
		    }
		});
		

   
		
	}
	public void nameMaker(){
		frame = new JFrame("Name");
		JPanel panel = new JPanel();
		Box box = new Box(BoxLayout.X_AXIS);
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

		JLabel label = new JLabel("Write your name");
		
		field = new JTextField(6);
		field.addActionListener(new FieldListener());
		JButton button = new JButton("Save");
		button.addActionListener(new ButtonListener());
		box.add(field);
		box.add(button);
		
		panel.add(BorderLayout.CENTER, label);
		panel.add(BorderLayout.SOUTH, box);
		
		frame.setResizable(false);
		frame.setDefaultCloseOperation(frame.DO_NOTHING_ON_CLOSE);
		frame.setSize(300,300);
		frame.add(BorderLayout.CENTER, panel);
		frame.pack();
		frame.setVisible(true);
		
	}
	
	
	public class TheButtonListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent ev) {
			try{
			writer.println(name + ": " + theField.getText());
			writer.flush();
			}catch(Exception ex){theField.setText("Couldn't send");theField.requestFocus();}
			theField.setText("");
			theField.requestFocus();
			
		}
		
		
	}
	
	public class TheFieldListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent ev) {
			try{
			writer.println(name + ": " + theField.getText());
			writer.flush();
			}catch(Exception ex){theField.setText("Couldn't send");theField.requestFocus();}
			theField.setText("");
			theField.requestFocus();
			
		}
		
		
	}
	
	private class TheFrameFocusListenr implements WindowFocusListener{


		@Override
		public void windowGainedFocus(WindowEvent e) {
			
			theField.requestFocus();
			
		}

		@Override
		public void windowLostFocus(WindowEvent e) {
			flashFocus = new Thread(new FlashFocusThread());
			flashFocus.start();
		}
		
		
	}
	
	private class FlashFocusThread implements  Runnable {
		public void run() {
			String message;
			
				try {
					while((message = reader.readLine()) != null){
						display.append(message + "\n");
						theFrame.requestFocus();
						theField.requestFocus();
						int x;
						display.selectAll();
						x = display.getSelectionEnd();
						display.select(x,x);
						
					}
				} catch (IOException e) {
					
				}
			
		}
	}
	
	public class ButtonListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent arg0) {
			
			name = field.getText();
			if (name.equals("")){
				name = "Bob";
			}
			frame.setVisible(false);
			whenUserJoins();
			
		}
		
		
	}
	
	public class FieldListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent arg0) {
			
			name = field.getText();
			if (name.equals("")){
				name = "Bob";
			}
			frame.setVisible(false);
			whenUserJoins();
			
		}
		
		
	}
	
	private void whenUserJoins(){
		
		setUpNetwork();
		go();
		theField.requestFocus();
	}
	
	private void setUpNetwork(){
		
		try {
			chatSocket = new Socket("ip_of_the_host", 5000);
			writer = new PrintWriter(chatSocket.getOutputStream());
			InputStreamReader stream = new InputStreamReader(chatSocket.getInputStream());
			reader = new BufferedReader(stream);
			try{
				writer.println(name);
				writer.flush();
				}catch(Exception ex){ex.printStackTrace();}

		} catch (UnknownHostException e) {
			display.setText("Unknown Host");
		} catch (IOException e) {
			display.setText("Server is probably off");
		}
		
	}
	
	public class MsgGetter implements Runnable{

		@Override
		public void run() {
				String message;
				try {
					while((message = reader.readLine()) != null){
						display.append(message + "\n");
						int x;
						display.selectAll();
						x = display.getSelectionEnd();
						display.select(x,x);
						
					}
				} catch (IOException e) {
					display.append("Server is probably off :/");
				}
		}
		
	}
	
	
	}










